<?php

namespace app\api\controller;

use think\Controller;
use think\facade\App;
use think\facade\Db;

class Basic
{
    protected $user = []; //存储人员信息
    protected $userid = 0;
    protected $role = 0; //人员类型 1为学员，2为教练
    protected $begin;
    protected $token = null;
    protected $table = '';
    public $msg = null;
    public $code = null;
    protected static $commonStaticLogic;

    public function __construct()
    {
        $this->begin = App::getBeginTime();
        $this->initParam();
    }

    private function initParam()
    {
        $token = !empty($_SERVER['HTTP_ACCESS_TOKEN']) ? $_SERVER['HTTP_ACCESS_TOKEN'] : input('token');
        $this->token = $token;
        config('session.session_id', $this->token);
        config('session.begin_time', $this->begin);
        //当前控制器
        config('cur_controller', $this);
    }

    /**
     * @param array $data
     * @param string $code
     * @param string $msg
     * @param string $type
     * @param array $header
     */
    public function json($data = [], $code = 1000, $msg = '', $type = 'json', array $header = [])
    {

        $execTime = $this->microtime_float() - $this->begin;

        $result = [
            'code' => $code,
            'message' => $msg,
            'time' => $execTime ? $execTime : time(),
            'result' => $data,
        ];

        return json($result);
    }

    /**
     * 新增 修改时记录数据 必须的三要素。
     * @param array $arr
     * @param int $new
     * @return array
     */
    public function buildArr($arr = [], $new = 0)
    {
        if ($new) {
            $arr['adduser'] = isset($arr['adduser']) && $arr['adduser'] ? $arr['adduser'] : $this->userid;
            $arr['addtime'] = time();
            $arr['updatetime'] = time();
            $arr['updateuser'] = isset($arr['adduser']) && $arr['adduser'] ? $arr['adduser'] : $this->userid;
        } else {
            $arr['updateuser'] = isset($arr['updateuser']) && $arr['updateuser'] ? $arr['updateuser'] : $this->userid;
            $arr['updatetime'] = time();
        }
        return $arr;
    }

    public function microtime_float()
    {
        list($usec, $sec) = explode(" ", microtime());
        return ((float) $usec + (float) $sec);
    }

    /**
     * @param array $data
     * @param string $code
     * @param string $msg
     * @param string $type
     * @param array $header
     */

    protected function getResponseType()
    {
        $isAjax = $this->app['request']->isAjax();
        $config = $this->app['config'];

        return $isAjax
        ? $config->get('default_ajax_return')
        : $config->get('default_return_type');
    }

    /**
     * 根据用户token获取用户信息
     */
    protected function getUserInfoByToken($table = null)
    {
        if (!$this->token) {
            return false;
        }
        $where = [];
        $where['token'] = $this->token;
        if ($table) {
            $where['table'] = $table;
        }
        $where['isdel'] = 0;
        $where['status'] = 1;
        $data['where'] = $where;
        $data['order'] = 'addtime desc';
        $info = $this->findTable("user_login", $data);

        return $info;
    }

    /**
     * 获取用户id
     * @return Ambigous <number, mixed, NULL, unknown>
     */
    protected function getUserId()
    {
        $userId = $this->session($this->_userIdName);

        return $userId > 0 ? $userId : 0;
    }

    /**
     * 把用户id存入session
     * @param number $userId
     * @return boolean|Ambigous <mixed, NULL, unknown>
     */
    protected function setUserId($userId)
    {
        if ($userId <= 0) {
            return false;
        }

        return $this->session($this->_userIdName, $userId);
    }

    /**
     * 从session获取当前登录的用户信息
     */
    protected function getUserInfo()
    {
        //登录成功之后把信息写入session，这里从session获取用户数据
        $userInfo = $this->session($this->_userInfoName);

        return !empty($userInfo) ? json_decode($userInfo, true) : array();
    }

    /**
     * 往session写入当前登录用户的信息
     */
    protected function setUserInfo($userInfo)
    {
        if (empty($userInfo)) {
            return false;
        }

        return $this->session($this->_userInfoName, json_encode($userInfo));
    }

    /**
     * session处理
     * @param string $name
     * @param string $value
     * @return Ambigous <mixed, NULL, unknown>
     */
    protected function session($name = '', $value = '')
    {
        return session($name, $value);
    }

    /**
     * 注销用户信息（用户退出操作）
     */
    protected function unsetUserInfo()
    {
        $this->session($this->_userIdName, null);
        $this->session($this->_userInfoName, null);
    }

    //分页需要的
    public function buildCount($data, $page = 1, $size = 0, $force = false)
    {
        if ($force) {
        } else {
            $page = input('pageNo', $page);
            $size = input('pageSize', $size);
        }

        if ($page < 1) {
            $page = 1;
        }
        if ($size < 1) {
            $size = 15;
        }
        $data['pageSize'] = isset($data['pageSize']) && $data['pageSize'] >= 1 ? (int) $data['pageSize'] : (int) $size;
        $data['pageNo'] = isset($data['pageNo']) && $data['pageNo'] >= 1 ? (int) $data['pageNo'] : (int) $page;
        $data['limitNo'] = ($data['pageNo'] - 1) * $data['pageSize'];
        $data['limitSize'] = $data['pageSize'];
        //总页数  linrongan
        if (!empty($data['totalCount'])) {
            $data['totalPage'] = ceil($data['totalCount'] / $data['pageSize']);
        } else {
            $data['totalPage'] = 1;
        }
        return $data;
    }

    /**
     * 获取数据库字段注释
     *https://www.4ui.cn/article/php/2OYVex0Gkd0q7pvA.html
     * @param string $table_name 数据表名称(必须，不含前缀)
     * @param string $field 字段名称(默认获取全部字段,单个字段请输入字段名称)
     * @param string $table_schema 数据库名称(可选)
     * @return string
     */
    public function getDbColumn($table_name = '', $field = true, $table_schema = '')
    {
        // 接收参数
        $database = config('database.connections.mysql');

        $table_schema = empty($table_schema) ? $database['database'] : $table_schema;
        $table_name = $database['prefix'] . $table_name;

        // 缓存名称
        $fieldName = $field === true ? 'allField' : $field;
        $cacheKeyName = 'db_' . $table_schema . '_' . $table_name . '_' . $fieldName;

        // 处理参数
        $param = [
            $table_name,
            $table_schema,
        ];

        // 字段
        $columeName = '';
        if ($field !== true) {
            $param[] = $field;
            $columeName = "AND COLUMN_NAME = ?";
        }

        // 查询结果
        $result = Db::query("SELECT COLUMN_NAME as field,column_comment as comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = ? AND table_schema = ? $columeName", $param);

        if (empty($result) && $field !== true) {
            return ['error' => $table_name . '表' . $field . '字段不存在'];
        }

        // 处理结果
        foreach ($result as $k => $v) {
            if (strpos($v['comment'], '#*#') !== false) {
                $tmpArr = explode('#*#', $v['comment']);
                $data[$v['field']] = $tmpArr[0];
            }
        }

        // 字段注释格式不正确
        if (empty($data)) {
            return ['error' => $table_name . '表' . $field . '字段注释格式不正确'];
        }

        return $data;
    }

    public function listTable($table, $data)
    {
        if (!$table) {
            return false;
        }
        if (!isset($data['where'])) {
            $data['where'] = [];
        }
        if (!isset($data['field'])) {
            $data['field'] = "*";
        }
        if (!isset($data['limitNo'])) {
            $data['limitNo'] = 0;
        }
        if (!isset($data['limitSize']) && !isset($data['nolimit'])) {
            $data['limitSize'] = 15;
        }
        if (!isset($data['order'])) {
            $data['order'] = "";
        }
        if (!isset($data['join'])) {
            $data['join'] = [];
        }
        if (!isset($data['having'])) {
            $data['having'] = "";
        }
        if (!isset($data['group'])) {
            $data['group'] = "";
        }

        try {
            $flag = false;
            if ($table == "????") {
                $flag = true;
            } elseif (!empty($data['debug'])) { //linrongan
                $flag = true;
            }
            $model = Db::name($table)->alias($table);
            if (!empty($data['join'])) {
                foreach ($data['join'] as $val) {
                    if (count($val) >= 2 && count($val) <= 3) {
                        $model->join($val[0], $val[1], empty($val[2]) ? 'inner' : $val[2]);
                    }
                }
            }
            $model = $model->where($data['where'])
                ->field($data['field'])
                ->order($data['order'])
                ->group($data['group'])
                ->having($data['having']);

            if(!isset($data['nolimit'])) {
                $model = $model->limit($data['limitNo'], $data['limitSize']);
            }


            $ans = $model
                ->fetchSql($flag)
                ->select();
            if ($flag) {
                return $ans;
            }
            return object_array(object_to_array($ans));
        } catch (\Exception $exception) {
            throw $exception;
        }
    }

    public function insertTable($table, $data, $type = "one")
    {
        if (!$table) {
            return false;
        }
        if (empty($data)) {
            return false;
        }

        ini_set('memory_limit', '2048M');
        if ($type == "one") {
            $data = $this->buildArr($data, 1);
            $ans = Db::name($table)->insertGetId($data);
        } else {
            foreach ($data as $key => $val) {
                $data[$key] = $this->buildArr($val, 1);
            }
            $ans = Db::name($table)->data($data)->insertAll();
        }
        return $ans;
    }

    public function updateTable($table, $data)
    {

        if (!$table) {
            return false;
        }

        if (empty($data['where'])) {
            return false;
        }

        if (empty($data['data'])) {
            return false;
        }
        if (!empty($data['debug'])) {
            $data['debug'] = true;
        } else {
            $data['debug'] = false;
        }

        $data['data'] = $this->buildArr($data['data']);
        $ans = Db::name($table)->where($data['where'])->strict(false)->fetchSql($data['debug'])->update($data['data']);
        return $ans;
    }

    public function destroy($table, $where)
    {
        $data = [
            'where' => $where,
            'data' => ['isdel' => time()],
        ];

        $ans = $this->updateTable($table, $data);
        return $ans;
    }

    public function deleteTable($table, $data)
    {
        if (!$table) {
            return false;
        }
        if (empty($data)) {
            return false;
        }
        $ans = Db::name($table)->where($data)->delete();
        return $ans;
    }

    public function countTable($table, $data)
    {

        if (!$table) {
            return false;
        }
        if (!isset($data['where'])) {
            $data['where'] = $data;
        }

        $data['join'] = isset($data['join']) ? $data['join'] : '';
        $data['group'] = isset($data['group']) ? $data['group'] : '';
        $flag = false;
        if (isset($data['debug']) && $data['debug']) {
            $flag = true;
        }
        $model = Db::name($table)->alias($table);
        if (!empty($data['join'])) {
            foreach ($data['join'] as $val) {
                if (count($val) >= 2 && count($val) <= 3) {
                    $model->join($val[0], $val[1], empty($val[2]) ? 'inner' : $val[2]);
                }
            }
        }
        return $model->where($data['where'])->group($data['group'])->fetchSql($flag)->count();
    }

    public function findTable($table, $data)
    {
        if (!$table) {
            return false;
        }
        if (empty($data['where'])) {
            return [];
        }
        if (!isset($data['field'])) {
            $data['field'] = "*";
        }
        if (!isset($data['order'])) {
            $data['order'] = "";
        }
        if (!isset($data['join'])) {
            $data['join'] = [];
        }
        $flag = false;
        if (!empty($data['debug'])) {
            $flag = true;
        }
        $model = Db::name($table)->alias($table);
        if (!empty($data['join'])) {
            foreach ($data['join'] as $val) {
                if (count($val) >= 2 && count($val) <= 3) {
                    $model->join($val[0], $val[1], empty($val[2]) ? 'inner' : $val[2]);
                }
            }
        }
        $ans = $model->where($data['where'])->field($data['field'])->order($data['order'])->fetchSql($flag)->find();
        if ($flag) {
            return $ans;
        }
        return object_to_array($ans);
    }

    public function getgaode($address)
    {
        $amapkey = config('param.amapkey');
        $url = 'https://restapi.amap.com/v3/geocode/geo' . "?address={$address}&output=json&key={$amapkey}";
        $result = curl_request($url, null);
        if (!empty($result)) {
            $result = json_decode($result);

            if ($result->infocode != 10000 || $result->status != 1) {
                return ['data' => $result, 'code' => 2000, 'msg' => empty($result->info) ? json_encode($result) : $result->info];
            } else {
                if (!empty($result->geocodes[0]->location)) {
                    $location = explode(',', $result->geocodes[0]->location);
                    return ['data' => $location, 'code' => 1000];
                } else {
                    return ['data' => $result, 'code' => 2000, 'msg' => '地址获取失败'];
                }
            }
        }
    }

    /**
     * 获取token
     */
    public function getToken($table, $info, $id)
    {
        if (empty($table) || empty($info)) {
            return false;
        }

        $token = md5($table . time() . $id);
        $data = [
            'adduser' => $id,
            'updateuser' => $id,
            'user' => json_encode($info, JSON_UNESCAPED_UNICODE),
            'status' => 1,
            'token' => $token,
            'side' => get_device_type(),
            'userid' => $id,
            'num' => 1,
            'table' => $table,
            'ip' => get_ip(),
        ];

        // 后面有必要就启用token 过期机制
        $update = [
            'where' => [
                'table' => $table,
                'status' => 1,
                'userid' => $id,
            ],
            'data' => ['status' => 0],
        ];

        Db::startTrans();

        $ans = $this->updateTable('user_login', $update);
        $row = $this->insertTable('user_login', $data);
        if (!$row) {
            Db::rollback();
            return false;
        }

        Db::commit();

        return $token;
    }

    public function buildSn()
    {
        $num = cache('date_order_sn' . date('Y-m-d'));
        if (!$num) {
            $dtime = strtotime(date('Y-m-d'));
            $countRow = $this->findTable('order', ['field' => 'count(distinct ordersn) as count', 'where' => [
                ['addtime', 'between', [strtotime(date('Y-m-d', time())), time()]],
            ]]);
            $num = 0;
            if (!empty($countRow)) {
                $num = $countRow['count'];
            }
        }
        $num = $num + 1;
        cache('date_order_sn' . date('Y-m-d'), $num);
        $num = sprintf('%03d', $num);
        return 'DD' . date('Ymd', time()) . $num . rand(100, 999);
    }

    /**
     * 生成订单号
     *
     * @return void
     */
    public function createOrdersn()
    {
        $order_id_main = date('YmdHis') . rand(1000000, 9999999);

        //订单号码主体长度
        $order_id_len = strlen($order_id_main);
        $order_id_sum = 0;

        for ($i = 0; $i < $order_id_len; $i++) {
            $order_id_sum += (int) (substr($order_id_main, $i, 1));
        }

        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

        mt_srand(10000000 * (float) microtime());
        for ($i = 0, $str = '', $lc = strlen($chars) - 1; $i < 2; $i++) {
            $str .= $chars[mt_rand(0, $lc)];
        }

        //唯一订单号码（YYYYMMDDHHIISSNNNNNNNNCC）
        $str3 = $order_id_main . str_pad((100 - $order_id_sum % 100) % 100, 2, '0', STR_PAD_LEFT);
        $yCode = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

        $orderSn = $yCode[intval(date('Y')) - 2011] . $str3 . $str;
        return $orderSn;
    }

    /**
     * memberid
     * coachid
     * source '1抢单，2邀请，3代下单 ',
     */
    public function addCustomer($data)
    {
        $where = ['memberid' => $data['memberid'], 'coachid' => $data['coachid']];
        $info = $this->findTable('customer', ['where' => $where]);
        if (empty($info)) {
            $ans = $this->insertTable('customer', $data);
            return $ans;
        } else {
            return false;
        }
    }

    public function addnotice($data, $type = "one")
    {
        $ans = $this->insertTable('notice', $data, $type);
        return $ans;

    }

    public function orderLog($data, $type = "one")
    {
        $ans = $this->insertTable('order_log', $data, $type);
        return $ans;
    }

    // CREATE TABLE `driv_finance` (
    //     `addtime` int(11) NOT NULL,
    //     `adduser` int(10) NOT NULL DEFAULT '0',
    //     `updatetime` int(11) NOT NULL,
    //     `updateuser` int(10) NOT NULL,
    //     `isdel` int(11) NOT NULL DEFAULT '0',
    //     `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1 默认为有效，0为无效，2为未注册',
    //     `revision` int(11) DEFAULT '0' COMMENT '乐观锁',
    //     `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
    //     `coachid` int(11) NOT NULL DEFAULT '0' COMMENT '教练id',
    //     `money` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '资金流水',
    //     `type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0: 首款, 1: 尾款, 2: 提现',
    //     PRIMARY KEY (`id`) USING BTREE
    //   ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='用户资金流水表';

    public function finance($data, $type = "one")
    {
        $ans = $this->insertTable('finance', $data, $type);
        return $ans;
    }

    /**
     *   `content` longtext NOT NULL COMMENT '业务回调信息',
     *  `errorinfo` varchar(255) NOT NULL COMMENT '错误信息',
     *  `param` text NOT NULL COMMENT '请求参数量',
     */
    public function setError($data)
    {
        $param = [
            'content' => print_r($data['content'], true),
            'errorinfo' => $data['errorinfo'],
            'param' => print_r($data['param'], true),
        ];
        $ans = $this->insertTable('payment_log', $param);

        return $ans;
    }

    public function resultsEndTo($data, $type = 0)
    {

        $performance = $this->countTable('performance', [
            'where' => [
                'source' => 'order',
                'sourceid' => $data['orderid'],
            ],
        ]);

        $where = ['coachid' => $data['coachid'], 'isdel' => 0, 'status' => 1];
        $coach_amount = $this->findTable('coach_amount', ['where' => $where]);

        if (empty($coach_amount)) {
            return false;
        }

        $price = bcdiv($data['price'], 2, 2);
        $describe = '订单尾款' . $price ;
        if ($performance > 2) {
            return false;
        }

        Db::startTrans();
        try {
            $param = [
                'coachid' => $data['coachid'],
                'memberid' => $data['memberid'],
                'amount' => $price,
                'type' => 1,
                'source' => 'order',
                'sourceid' => $data['orderid'],
                'describe' => $describe,
            ];

            $fdata = [
                'coachid' => $data['coachid'],
                'money' => $price,
                'type' => 2,
            ];
            $ans = $this->insertTable('performance', $param);
            $finance = $this->insertTable('finance', $fdata);

            $amoundata = [
                'data' => [
                    'totalamount' => bcadd($coach_amount['totalamount'], $price, 2),
                    'revision' => $coach_amount['revision'] + 1,
                ],
                'where' => [
                    'id' => $coach_amount['id'],
                    'revision' => $coach_amount['revision'],
                ],
            ];
            $arow = $this->updateTable('coach_amount', $amoundata);

            $timingdata = [
                'data' => [
                    'status' => 2,
                    'revision' => $data['revision'] + 1,
                ],
                'where' => [
                    'id' => $data['id'],
                    'revision' => $data['revision'],
                ],
            ];
            $row = $this->updateTable('order_timing', $timingdata);

            $update = [
                'where' => ['orderid' => $data['orderid']],
                'data' => [
                    'status' => 6,
                ],
            ];
            $oans = $this->updateTable('order', $update);

            $commis = $this->commission($data['orderid']);

            // 提交事务
            if ($ans && $row && $arow && $oans && $finance && $commis) {
                Db::commit();
                $content = [];
                $errorinfo = '执行成功';
                $status = 1;
                $log = [
                    'orderstatus' => 6,
                    'orderid' => $data['orderid'],
                    'userid' => $data['adduser'],
                    'table' => 'member',
                    'desc' => $type == 0 ? "订单自动确认完成" : '订单确认完成',
                ];
                $this->orderLog($log);
            } else {
                Db::rollback();
                if ($ans == 0) {
                    $errorinfo = '业绩记录失败';
                    $content = $param;
                } else if ($row == 0) {
                    $errorinfo = '订单定时记录核销失败';
                    $content = $timingdata;
                } else if ($finance == 0) {
                    $errorinfo = '订单流水记录失败';
                    $content = $fdata;
                } else if ($arow == 0) {
                    $errorinfo = '个人余额写入失败';
                    $content = $amoundata;
                } else if ($oans == 0) {
                    $errorinfo = '订单更新失败';
                    $content = $update;
                } else {
                    $errorinfo = 'resultsTo函数执行失败';
                }
                $status = 0;
            }
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            $content = [];
            $status = 0;
            $errorinfo = 'resultsTo-逻辑执行报错' . $e->getMessage();
        }

        $error = [
            'status' => $status,
            'content' => $content,
            'errorinfo' => $describe . $errorinfo,
            'param' => $data,
        ];
        $this->setError($error);
        return true;
    }

    public function commission($orderId = 0)
    {
        if(empty($orderId)) {
            return false;
        }

        //获取订单
        $where = [
            'orderid' => $orderId,
        ];

        $order = $this->findTable('order', ['where' => $where]);

        if(empty($order)) {
            return false;
        }

        $coachId = $order['coachid'];

        //获取逻辑理应使用遍历，现临时处理
        //获取教练
        $coach = $this->findTable('coach', ['coachid' => $coachId]);

        //获取校长
        $principal = $this->findTable('coach', ['agent_id' => $coach['agent_id']]);

        //服务经理
        $manager = $this->findTable('coach', ['agent_id' => $principal['agent_id']]);

        //分佣
        $commission = array(
            'coach' => 0.6,
            'principal' => 0.3,
            'manager' => 0.1
        );

        //获取订单支付金额的10%
        $price = $order['price'] * 0.1;

        /* 发放金额记录  */

        //教练
        $this->insertTable('finance_log', [
            'user_id' => $coach['coachid'],
            'mode' => 0,
            'amount' => $price * $commission['coach']
        ]);
        //教练账号入账流程

        //校长
        if(!empty($principal)) {
            $this->insertTable('finance_log', [
                'user_id' => $principal['principal'],
                'mode' => 0,
                'amount' => $price * $commission['coach']
            ]);
            //校长账号入账流程
        }

        //经理
        if(!empty($manager)) {
            $this->insertTable('finance_log', [
                'user_id' => $manager['coachid'],
                'mode' => 0,
                'amount' => $price * $commission['manager']
            ]);
            //经理账号入账流程
        }

        return true;

    }

}
